package pe.gob.servir.apps.censodirectivo.ejb.dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import oracle.jdbc.OracleTypes;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;

import pe.gob.servir.apps.censodirectivo.common.constantes.Constantes;
import pe.gob.servir.apps.censodirectivo.common.dao.AbstractJPABaseDAO;
import pe.gob.servir.apps.censodirectivo.common.util.Utilitario;
import pe.gob.servir.apps.censodirectivo.excepcion.DAOExcepcion;
import pe.gob.servir.apps.censodirectivo.model.bean.MensajeRespuesta;
import pe.gob.servir.apps.censodirectivo.model.bean.Plantilla;
import pe.gob.servir.apps.censodirectivo.persistence.entity.TblPlantilla;

/**
 * Session Bean implementation class PlantillaDAO
 */
@Stateless
public class PlantillaDAO extends AbstractJPABaseDAO<TblPlantilla> implements PlantillaDAOLocal {
	
	private static final Logger log = Logger.getLogger(PlantillaDAO.class);
	
	@EJB
	private ConsumirProcedimientoDAOLocal consumirProcedimientoDAOLocal;	
	
	@PersistenceContext(unitName = "persistenceUnitCenso")
	EntityManager entityManager;

    public PlantillaDAO() {
    	super(TblPlantilla.class);
    }

	@Override
	protected EntityManager getEntityManager() {
		return entityManager;
	}

	@Override
	public MensajeRespuesta insertarPlantilla(final long plantillaId,final long censoId,
			final long tipoPlantilla,final String asunto,final String cuerpo,
			final Date fechaCreacion,final String usuarioCreador,
			final Date fechaModificacion,final String usuarioModificador,
			final String estadoRegistro) throws DAOExcepcion {
		Session session = entityManager.unwrap(Session.class);
		final MensajeRespuesta mensajeRespuesta = new MensajeRespuesta();
		try {
			session.doWork(new Work() {
				@Override
				public void execute(Connection connection) throws SQLException {
					CallableStatement callableStatement = null;
					ResultSet resultset = null;
					try {
							connection.setAutoCommit(false);
							callableStatement = connection.prepareCall(Constantes.SP_INSERTAR_PLANTILLA);
							callableStatement.setLong("E_PLANTILLA_ID", plantillaId);
							callableStatement.setLong("E_CENSO_ID", censoId);
							callableStatement.setLong("E_TIPO_PLANTILLA_ID", tipoPlantilla);
							callableStatement.setString("E_ASUNTO", asunto);
							callableStatement.setString("E_CUERPO", cuerpo);
							callableStatement.setString("E_USUARIO", usuarioCreador);
							callableStatement.setString("E_ESTADO_REGISTRO", estadoRegistro);
							callableStatement.registerOutParameter("S_ID_ERROR", OracleTypes.INTEGER);
							callableStatement.registerOutParameter("S_DES_ERROR", OracleTypes.VARCHAR);
							callableStatement.registerOutParameter("S_DES_ERROR_INFO", OracleTypes.VARCHAR);
							callableStatement.execute();
						
							log.info("Se ejecuto exitosamente el SP.");
							int codigoError = callableStatement.getInt("S_ID_ERROR");
							String mensajeError = callableStatement.getString("S_DES_ERROR");
							String mensajeErrorInfo = callableStatement.getString("S_DES_ERROR_INFO");							
							mensajeRespuesta.setCodigoError(String.valueOf(codigoError));
							mensajeRespuesta.setMensajeError(mensajeError);
							mensajeRespuesta.setMensajeInfo(mensajeErrorInfo);
							
							if (codigoError == 0) {
								log.info("Se registro datos con exito en BD.");
								connection.commit();
							} else {
								log.info("No se pudo registrar los datos en BD. " + mensajeErrorInfo);
								throw new SQLException();
							}
					} catch(SQLException e) {
						if (mensajeRespuesta.getMensajeInfo() != null){
							log.error("SQLException : " + mensajeRespuesta.getMensajeInfo());
						}
						connection.rollback();
						throw e;
					} catch (Exception e) {
						log.error("Exception : " + e.getMessage(), e);
						connection.rollback();
						throw e;
					} finally {
						Utilitario.cerrarConexiones(resultset, callableStatement);
					}
				}
			});
		} catch (Exception e) {
			if (mensajeRespuesta.getCodigoError() == null) {
				String mensajeError = consumirProcedimientoDAOLocal.consultarMensaje(Constantes.CODIGO_MSJ_ERROR_DB);
				throw new DAOExcepcion(Constantes.CODIGO_MSJ_ERROR_DB, mensajeError);
			}
			throw new DAOExcepcion(mensajeRespuesta.getCodigoError(), mensajeRespuesta.getMensajeError());
		}
		return mensajeRespuesta;
	}

	@Override
	public Plantilla consultarPlantilla(final Plantilla plantillaIn) throws DAOExcepcion{
		Session session = entityManager.unwrap(Session.class);
		final Plantilla plantilla = new Plantilla();
		try {
		session.doWork(new Work() {
			@Override
			public void execute(Connection connection) throws SQLException {
				ResultSet resultset = null;
				PreparedStatement preparedStatement = null;
				String sql = "SELECT * FROM VW_CONSULTA_PLANTILLAS WHERE CENSO_ID = ? AND TIPO_PLANTILLA_ID = ? ";
				try {
					preparedStatement = connection.prepareStatement(sql);
					preparedStatement.setLong(1, plantillaIn.getCensoId());
					preparedStatement.setLong(2, plantillaIn.getTipoPlantillaId());
					resultset =	preparedStatement.executeQuery();
					log.info("Se ejecuto consulta con exito.");
					while (resultset.next()) {
						plantilla.setPlantillaId(resultset.getLong("PLANTILLA_ID"));
						plantilla.setCensoId(resultset.getLong("CENSO_ID"));
						plantilla.setTipoPlantillaId(resultset.getLong("TIPO_PLANTILLA_ID"));
						plantilla.setAsunto(resultset.getString("ASUNTO"));
						plantilla.setCuerpo(resultset.getString("CUERPO"));
						plantilla.setEstadoRegistro(resultset.getString("ESTADO_REGISTRO"));
					}
				} catch(SQLException e) {
					log.error("SQLException : " , e);
					throw e;
				} catch (Exception e) {
					log.error("Exception : " , e);
					throw e;
				} finally {
					Utilitario.cerrarResultset(resultset);
					Utilitario.cerrarPreparedStatement(preparedStatement);
				}
			}
		});
		} catch (Exception e) {
			String mensajeError = consumirProcedimientoDAOLocal.consultarMensaje(Constantes.CODIGO_MSJ_ERROR_DB);
			throw new DAOExcepcion(Constantes.CODIGO_MSJ_ERROR_DB, mensajeError);
		}
		return plantilla;
	}
	
	
	@Override
	public List<Plantilla> listarPlantillas(final Plantilla plantilla) throws DAOExcepcion {
		log.info("Parametro Entrada [PlantillaId]: " + plantilla.getPlantillaId());
		log.info("Parametro Entrada [CensoId]: " + plantilla.getCensoId());
		log.info("Parametro Entrada [TipoPlantillaId]: " + plantilla.getTipoPlantillaId());		
		Session session = entityManager.unwrap(Session.class);
		final List<Plantilla> listaPlantillasSP = new ArrayList<Plantilla>();
		try {
		session.doWork(new Work() {
			@Override
			public void execute(Connection connection) throws SQLException {
				CallableStatement callableStatement = null;
				ResultSet resultset = null;
				try {
					callableStatement = connection.prepareCall(Constantes.SP_CONSULTAR_PLANTILLA);
					callableStatement.setLong(1, plantilla.getPlantillaId());
					callableStatement.setLong(2, plantilla.getCensoId());
					callableStatement.setLong(3, plantilla.getTipoPlantillaId());					
					callableStatement.registerOutParameter(4, OracleTypes.CURSOR);
					callableStatement.registerOutParameter(5, OracleTypes.INTEGER);
					callableStatement.registerOutParameter(6, OracleTypes.VARCHAR);
					callableStatement.execute();
					log.info("Se ejecuto exitosamente el SP.");
					resultset = (ResultSet) callableStatement.getObject(4);//Cursor
					
					while (resultset.next()) {
						Plantilla plantilla = new Plantilla();
						plantilla.setCensoId(resultset.getLong("CENSO_ID"));
						plantilla.setPlantillaId(resultset.getLong("PLANTILLA_ID"));
						plantilla.setTipoPlantillaId(resultset.getLong("TIPO_PLANTILLA_ID"));
						plantilla.setAsunto(resultset.getString("ASUNTO"));
						plantilla.setCuerpo(resultset.getString("CUERPO"));
						listaPlantillasSP.add(plantilla);
					}

				} finally {
					Utilitario.cerrarConexiones(resultset, callableStatement);
				}
			}
		});
		
		} catch (Exception e) {
			String mensajeError = consumirProcedimientoDAOLocal.consultarMensaje(Constantes.CODIGO_MSJ_ERROR_DB);
			throw new DAOExcepcion(Constantes.CODIGO_MSJ_ERROR_DB, mensajeError);
		}
		
		return listaPlantillasSP;
	}

}
